package utils

import (
	"fmt"
	"github.com/pkg/errors"
	"os"
	"strings"
	"syscall"
	"unsafe"
)

func GetFstatInfo() (*FstatInfo, error) {
	kernel32, err := syscall.LoadLibrary("Kernel32.dll")
	if err != nil {
		return nil, errors.Wrap(err, "load win32 library failed")
	}
	defer func() {
		err = syscall.FreeLibrary(kernel32)
		if err != nil {
			println("free library failed")
		}
	}()

	GetDiskFreeSpaceEx, err := syscall.GetProcAddress(kernel32, "GetDiskFreeSpaceExW")
	if err != nil {
		return nil, errors.Wrap(err, "syscall get process address failed")
	}

	lpFreeBytesAvailable := int64(0)
	lpTotalNumberOfBytes := int64(0)
	lpTotalNumberOfFreeBytes := int64(0)

	wd, err := os.Getwd()
	if err != nil {
		return nil, errors.Wrap(err, "get cwd failed")
	}
	if len(wd) < 1 {
		return nil, errors.New("get cwd response empty!")
	}

	disk := strings.ToUpper(fmt.Sprintf("%c:", wd[0]))
	syscall.Syscall6(GetDiskFreeSpaceEx, 4,
		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(disk))),
		uintptr(unsafe.Pointer(&lpFreeBytesAvailable)),
		uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
		uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)), 0, 0)

	var out = &FstatInfo{
		Total: int(lpTotalNumberOfBytes),
		Avail: int(lpFreeBytesAvailable),
	}
	out.Used = out.Total - out.Avail
	return out, nil
}
